using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Microsoft.Extensions.Configuration;

namespace 综合同步
{
    class LocalServer
    { 
        static LocalServer _inst;
        private NetTcpServer server;
        private RedisClientBll redis;
        public bool m_bSaveData = false;
        public string[] directory;
        static object _mutex = new object();
        public FixDataBase m_db = new FixDataBase();
        private TcmsComRev<TCMSRecvPackage_BJ> m_serial;

        private string infoSection;//车辆区间
        public string Section{
            get{lock(this) return infoSection;}
            set{lock(this) infoSection = value;}
        }
        #region 配置
        private static IConfigurationRoot m_configuration;
        private static ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
        private static IConfigurationRoot configuration{
            get{
                if(m_configuration==null){
                    configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
                    m_configuration = configurationBuilder.Build();
                }
                return m_configuration;
            }
        }
        #endregion
        public static LocalServer instance()
        {
            lock(_mutex)
            {
                if(_inst==null)
                    _inst = new LocalServer();
            }
            return _inst;
        }
        private LocalServer()
        {
            directory = m_db.LineInfoEntities.ToList().Select(o=>
                Path.Combine(GetConfigValue<string>("DataPath"),o.LineName)).ToArray();
            if(GetConfigValue<bool>("Vehicle System:Enable")){
                server = new NetTcpServer(GetConfigValue<ushort>("Vehicle System:TCP:LocalPort"));
                server.envSendTargetData+=Recv;
                m_serial = new TcmsComRev<TCMSRecvPackage_BJ>(GetConfigValue<string>("Vehicle System:COM"));
                redis = new RedisClientBll(GetConfigValue<string>("Vehicle System:Redis:IP"), 
                    GetConfigValue<ushort>("Vehicle System:Redis:Port"),GetConfigValue<string>("Vehicle System:Redis:Password"));
            }
        }
        public static T GetConfigValue<T>(string key)
        {
            return configuration.GetValue<T>(key);
        }
        public NetTcpServer GetServer() { return server; }
        void Recv(DataType type, EndPoint point, object data)
        {
            switch (type)
            {
                case DataType.NetConnected:
                {
                    TcpClient client = data as TcpClient;
                    PACKAGE_INFO packet = new PACKAGE_INFO() { packtype = (uint)PacketType.TimeSync };
                    Int64 timestamp = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1, 8, 0, 0, 0)).TotalSeconds);
                    LocalServer.instance().GetServer().SendData(client,packet.FromPackage(BitConverter.GetBytes(timestamp)));
                    if(!string.IsNullOrEmpty(LocalServer.instance().Section)){
                        packet.packtype = (uint)PacketType.StationChange;
                        LocalServer.instance().GetServer().SendData(client,
                            packet.FromPackage(Encoding.Default.GetBytes(LocalServer.instance().Section)));
                    }
                    switch((point as IPEndPoint).Port)
                    {
                        case (int)ChannelType.ARC:
                            FileLogOperator.Info("燃弧软件连接成功.");
                            break;
                        case (int)ChannelType.HANG:
                            FileLogOperator.Info("悬挂软件连接成功.");
                            break;
                        case (int)ChannelType.PRESS:
                            FileLogOperator.Info("压力硬点软件连接成功.");
                            break;
                        case (int)ChannelType.TEMPERATURE:
                            FileLogOperator.Info("红外软件连接成功.");
                            break;
                        case (int)ChannelType.VIDEO:
                            FileLogOperator.Info("视频软件连接成功.");
                            break;
                        default:break;
                        }
                    break;
                }
                case DataType.NetClose:
                {
                    switch ((point as IPEndPoint).Port)
                    {
                        case (int)ChannelType.ARC:
                            FileLogOperator.Info("燃弧软件断开连接.");
                            break;
                        case (int)ChannelType.HANG:
                            FileLogOperator.Info("悬挂软件断开连接.");
                            break;
                        case (int)ChannelType.PRESS:
                            FileLogOperator.Info("压力硬点软件断开连接.");
                            break;
                        case (int)ChannelType.TEMPERATURE:
                            FileLogOperator.Info("红外软件断开连接.");
                            break;
                        case (int)ChannelType.VIDEO:
                            FileLogOperator.Info("视频软件断开连接.");
                            break;
                        default: break;
                    }
                    break;
                }
                case DataType.NetRecieve:
                {
                    switch ((point as IPEndPoint).Port)
                    {
                        case (int)ChannelType.ARC:
                            FileLogOperator.Info("收到燃弧软件数据.");
                            break;
                        case (int)ChannelType.HANG:
                            FileLogOperator.Info("收到悬挂软件数据.");
                            break;
                        case (int)ChannelType.PRESS:
                            FileLogOperator.Info("收到压力硬点软件数据.");
                            break;
                        case (int)ChannelType.TEMPERATURE:
                            FileLogOperator.Info("收到红外软件数据.");
                            break;
                        case (int)ChannelType.VIDEO:
                            FileLogOperator.Info("收到视频软件数据.");
                            break;
                        default: break;
                    }
                    break;
                }
                case DataType.LogInfo:
                {
                    break;
                }
                default:break;
            }
        }
    }
}